/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

import java.net.*;
import java.io.*;
import java.util.*;
import nanoxml.XMLElement;

/**
 *
 * @author marduke
 */
public class ServidorNodo extends Thread {

    ServerSocket providerSocket;
    Socket connection = null;
    ObjectOutputStream out;
    ObjectInputStream in;
    String message;
    Vector vecinos = new Vector();
    Vector archivos = new Vector();
    String directorio = new String();

    public ServidorNodo(Vector vecinos, Vector archivos, String directorio) {
        this.vecinos = vecinos;
        this.archivos = archivos;
        this.directorio = directorio;
    }

    public void run() {

        while (true) {
            this.corrida();
        }

    }

    void corrida() {
        try {
            String retorno = new String();
            //1. creating a server socket
            providerSocket = new ServerSocket(1800, 10);
            //2. Wait for connection
            System.out.println("Esperenado por una conexion, Soy el servidor host");
            connection = providerSocket.accept();
            System.out.println("La conexion se recibio desde: " + connection.getInetAddress().getHostName());
            //3. get Input and Output streams
            out = new ObjectOutputStream(connection.getOutputStream());
            out.flush();
            in = new ObjectInputStream(connection.getInputStream());
            sendMessage("Connection successful");
            //4. The two parts communicate via the input and output streams
            do {
                try {
                    message = (String) in.readObject();
                    Scanner sc = new Scanner(message);
                    
                    

                    if (sc.hasNext()) {
                        String tmp = sc.next();
                        if (tmp.compareTo("Alcanzable") == 0) {
                            String xml = sc.nextLine();
                            XMLElement visitados = new XMLElement();
                            visitados.parseString(xml);

                            System.out.println(visitados.toString());

                            message = alcanzable(vecinos, visitados);
                            sendMessage(message);

                        } else if (tmp.equals("Consulta")) {

                            
                            String arg1 = sc.next();
                            String arg2 = sc.nextLine();
                            String prueba[] = arg2.split("%-XCTW-%");
                            System.out.println(arg2);
                            try {
                                System.out.println("MMALO DEBERIAS ENTRAR AQUI!!!" + prueba[0] + " " + prueba[1] + " " +prueba[2]);
                                message = consulta(directorio, arg1, prueba[0], prueba[1], prueba[2]);
                                sendMessage(message);
                            } catch (Exception e) {
                                e.printStackTrace();
                            }



                        } else if (tmp.equals("bye")) {

                            sendMessage("bye");
                        } else {
                            System.out.println(message);
                            message = "Error";
                            sendMessage(message);
                        }
                    }





                } catch (ClassNotFoundException classnot) {
                    System.err.println("Data received in unknown format");
                }
            } while (!message.equals("bye"));
        } catch (SocketException socketE) {
            System.out.println("Hubo un error en el socket, este el servidor Nodo");
            System.exit(6);
        } catch (IOException ioException) {
            ioException.printStackTrace();
        } finally {
            //4: Closing connection
            try {
                in.close();
                out.close();
                providerSocket.close();
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }
        }

    }

    String alcanzable(Vector vecinos, XMLElement visitados) throws UnknownHostException {

        System.out.println("<<<<<<<<<<<<<<<ESTOY EN LA FUNCION ALCANZABLE>>>>>>>>>>>>");

        String messageToServer;
        String xmlre = new String();
        String retorno = new String();
        InetAddress addr = InetAddress.getLocalHost();
        String hostAddress = addr.getHostAddress();


        XMLElement child = new XMLElement();
        child.setName("elemento");
        child.setAttribute("hostAddress", addr.getHostAddress());
        child.setAttribute("hostName", addr.getHostName());

        visitados.addChild(child);

        System.out.println(visitados.toString());


        xmlre = visitados.toString();
        messageToServer = "Alcanzable " + xmlre;
        System.out.println(messageToServer);

        System.out.println("Ahi: " + vecinos.size() + " en este ejemplo.");
        Iterator<String> it = vecinos.iterator();
        while (it.hasNext()) {
            String vecino = it.next();


            if(!fueVisitado(xmlre,vecino)) {
            ClienteNodo clienteN = new ClienteNodo(messageToServer, vecino);
            String tmp = clienteN.run();
            if(!tmp.equals("Error")) {
                xmlre = tmp;
            }

            } else {
                System.out.println("Este ya fue visitado.");
            }
            messageToServer = "Alcanzable " + xmlre;
            System.out.println(messageToServer + " " + vecinos.size());

        }
        retorno = xmlre;
        System.out.println("<<<<<<<<<<<<<<<SALI DE LA FUNCION ALCANZABLE>>>>>>>>>>>>");
        return retorno;
    }

    boolean fueVisitado(String xml, String vecino) {

        boolean retorno = false;

        try {

            XMLElement visitados = new XMLElement();
            visitados.parseString(xml);

            Enumeration childs = visitados.enumerateChildren();
            while (childs.hasMoreElements()) {
                XMLElement child = (XMLElement) childs.nextElement();
                String hostname = (String) child.getAttribute("hostName");
                String hostaddress = (String) child.getAttribute("hostAddress");

                //System.out.println("Hostname: "+ hostname);

                if (hostaddress.equals(vecino) || hostname.equals(vecino)) {
                    return true;
                }
            }

        } catch (Exception uhE) {
            System.out.println("No tiene ningun servidor.");
        }



        return false;
    }

    void sendMessage(String msg) {
        try {
            out.writeObject(msg);
            out.flush();
            System.out.println("serverNodo>" + msg);
        } catch (IOException ioException) {
            ioException.printStackTrace();
        }
    }

    String consulta(String dirArchivos, String tipo, String cadena, String consulta, String visitado) throws Exception {
        
        XMLElement retorno = new XMLElement();
        System.out.println(consulta);

        XMLElement conXml = new XMLElement();
        conXml.parseString(consulta);

        XMLElement visXml = new XMLElement();
        visXml.parseString(visitado);

        InetAddress addr = InetAddress.getLocalHost();

        String messageToServer;

        

        XMLElement child = new XMLElement();
        child.setName("elemento");
        child.setAttribute("hostAddress", addr.getHostAddress());
        child.setAttribute("hostName", addr.getHostName());

        visXml.addChild(child);

        Iterator<String> ite = archivos.iterator();
        while (ite.hasNext()) {
            String npi = (String) ite.next();
            XMLElement children = consultaXML(dirArchivos, npi, tipo, cadena, conXml);
            conXml.addChild(children);
        }

        System.out.println(retorno.toString());
        String xmlre = visXml.toString();
        String xmlco = conXml.toString();

        messageToServer = "Consulta " + tipo + " " + cadena + "%-XCTW-%" + xmlco + "%-XCTW-%" + xmlre;

        Iterator<String> it = vecinos.iterator();
        while (it.hasNext()) {
            String vecino = it.next();

            if (!fueVisitado(xmlre, vecino)) {
                ClienteNodo clienteN = new ClienteNodo(messageToServer, vecino);
                String tmp = clienteN.run();
                String tmp2[] = tmp.split("%-XCTW-%");
                xmlre = tmp2[1];
                xmlco = tmp2[0];
            } else {
                System.out.println("Este ya fue visitado.");
            }
            messageToServer = "Consulta " + tipo + " " + cadena + "%-XCTW-%" + xmlco + "%-XCTW-%" + xmlre;
            System.out.println(messageToServer + " " + vecinos.size());

        }



        return xmlco + "%-XCTW-%" + xmlre;
    }

    private XMLElement consultaXML(String dirArchivo, String archivo, String tipo, String cadena, XMLElement conXml) {
        XMLElement retorno = new XMLElement();

        try {

            String autor = "";
            String titulo = "";
            String descripcion = "";

            XMLElement xml = new XMLElement();
            FileReader reader = new FileReader(dirArchivo + "/" + archivo + ".xml");
            xml.parseFromReader(reader);


            Enumeration children = xml.enumerateChildren();
            if (tipo.compareTo("clave") == 0) {
                while (children.hasMoreElements()) {
                    XMLElement child = (XMLElement) children.nextElement();
                    if (child.getName().compareTo("palabrasClave") == 0) {
                        Enumeration children2 = child.enumerateChildren();
                        while (children2.hasMoreElements()) {
                            XMLElement child2 = (XMLElement) children2.nextElement();
                            System.out.println(child2.getAttribute("palabra"));
                            if (((String) child2.getAttribute("palabra")).contains(cadena)) {
                                Enumeration children3 = xml.enumerateChildren();
                                XMLElement child3 = (XMLElement) children.nextElement();
                                if (child.getName().compareTo("titulo") == 0) {
                                    titulo = child.getContent();
                                    System.out.println(titulo);
                                } else if (child.getName().compareTo("descripcion") == 0) {
                                    descripcion = child.getContent();
                                    System.out.println(descripcion);
                                } else if (child.getName().compareTo("autor") == 0) {
                                    autor = child.getContent();
                                    System.out.println(autor);
                                }
                                retorno = enviarConsulta(archivo + ".jpg", titulo, autor, descripcion);
                                

                            }
                        }
                    }
                }
            } else {

                while (children.hasMoreElements()) {
                    XMLElement child = (XMLElement) children.nextElement();
                    if (child.getName().compareTo("titulo") == 0) {
                        if (((String) child.getContent()).contains(cadena)) {
                            Enumeration children3 = xml.enumerateChildren();
                            XMLElement child3 = (XMLElement) children.nextElement();
                            if (child.getName().compareTo("titulo") == 0) {
                                titulo = child.getContent();
                                System.out.println(titulo);
                            } else if (child.getName().compareTo("descripcion") == 0) {
                                descripcion = child.getContent();
                                System.out.println(descripcion);
                            } else if (child.getName().compareTo("autor") == 0) {
                                autor = child.getContent();
                                System.out.println(autor);
                            }
                          retorno = enviarConsulta(archivo + ".jpg", titulo, autor, descripcion);
                        }
                    }
                }
            }
        } catch (Exception e) {
        }

        return retorno;
    }

    private XMLElement enviarConsulta(String nombreArchivo, String titulo, String autor, String descripcion) throws Exception {
        XMLElement consulta = new XMLElement();
        consulta.setName("maquina");

        InetAddress adr = InetAddress.getLocalHost();

        consulta.setAttribute("hostname", adr.getHostAddress());

        XMLElement child = new XMLElement();
        child.setName("foto");
        child.setAttribute("nombreArchivo", nombreArchivo);
        child.setAttribute("autor", autor);
        child.setAttribute("titulo", titulo);
        child.setAttribute("descripcion", descripcion);

        consulta.addChild(child);

        return consulta;
    }
}
